In any substantial software development project, the identification and correction of bugs and other erroneous or undesirable program behavior is a challenging task. Debugging of software developed for embedded systems is often especially difficult. Program errors may be visible on hardware only in real time, or they may be intermittent and nondeterministic. Conventional debugging tools are typically not an adequate solution for correcting such relatively complex software problems.
Some microprocessor architectures, including certain architectures used for embedded systems, have been designed with high-speed trace ports that facilitate the outputting of cycle-by-cycle trace data about the status of the processor when code is executed. In essence, hardware trace data comprises a complete log of instructions executed by the processor. Trace data may also include information regarding data read from and written to memory, as well as information regarding the occurrence of context switches and operating system interrupts. This information is highly useful for debugging embedded applications and the like by providing visibility. When a system crash occurs, the availability of trace data, coupled with appropriate software tools for trace analysis, enables the developer to reconstruct the program flow to see precisely what the program was doing at the time of the crash.
For many microprocessors, unfortunately, there is no hardware facility that generates trace data. To achieve useful visibility of execution behavior comparable to that provided by way of hardware-generated trace data, developers of applications for non-trace architectures often instrument the code. Instrumentation has certain drawbacks, particularly the accompanying increase in the size and slowdown in the execution speed of programs under development. Existing industry instrumentation solutions have required preprocessing and recompilation of source code in order to insert instrumentation tags. Typically, several instructions are generated for each instrumentation point. For large applications, compile-time or pre-compilation instrumentation entails undesirably long build times and complex management of multiple versions of the software system under development. The debugging process is also adversely affected when code is instrumented at compile time.
Today's microprocessors typically include on-chip memory management units that, given appropriate support from a memory-protected operating system, enable individual threads of execution to run in hardware-protected private virtual address spaces. Memory-protected operating systems improve the reliability of software and facilitate debugging. A potential drawback to existing instrumentation solutions is that they often provide for instrumenting a single execution address space.